package com.best.oasis.settlement.dao.security;

import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
import org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
import org.springframework.security.ldap.LdapUserSearch;
import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Repository;

import com.best.oasis.settlement.common.entity.security.User;
import com.best.oasis.settlement.common.entity.security.UserGroupMapping;
import com.best.oasis.settlement.common.entity.security.UserRoleMapping;
import com.best.oasis.settlement.common.error.ErrorCode;
import com.best.oasis.settlement.dao.base.BaseDaoImpl;
import com.best.oasis.settlement.util.LDAPUtil;
import com.best.oasis.settlement.util.exception.DAOException;
import com.best.oasis.settlement.util.security.BestLdapUserDetailsMappper;
@Repository
public class UserDaoImpl extends BaseDaoImpl<User, Long> implements UserDao, UserDetailsService  {
    /**
     * Logger for this class
     */
    private static final Logger   logger          = Logger.getLogger(UserDaoImpl.class);
	
	protected static final String GET_BY_USERNAME = "getByUserName";
	
	protected static final String GET_BY_GROUP_ID = "getUsersByRoleGroupId";
	
    @Autowired 
    private LdapUserSearch userSearch;
    @Autowired
    private RoleDao roleDao;
    /**
     * Constructor that sets the entity to User.class.
     */
    public UserDaoImpl() {
        super(User.class);
    }
	/**
	 *  从LdapServer获得用户信息
	 * @throws Exception 
	 *
	 */
    public User getUserInfoFromLdapServer(String userName) throws Exception{
    	User result = null;
    	try{
    		DirContextOperations ctx;
    		if( LDAPUtil.getUserType(userName ) == LDAPUtil.USER_TYPE_HT ){
    			FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("", LDAPUtil.getSearchFilter(), getContextSource( userName ));
  		        locator.setSearchSubtree(true);
	  			//汇通员工
	  			ctx = locator.searchForUser(userName);
  			
    		}else{
    			//best员工
    			ctx = userSearch.searchForUser(userName);
    		}
        	BestLdapUserDetailsMappper mapper = new BestLdapUserDetailsMappper();
        	result = mapper.mapUserFromContext(ctx, userName, null);
        	
        	return result;
    	}
    	catch(UsernameNotFoundException e){
    		return result;
    	}

    	
    }
    
    public BaseLdapPathContextSource getContextSource( String userName ) throws Exception {
    	//String url= "ldap://Htdc3.ht.800best.net:389/dc=ht,dc=800best,dc=net";
    	String url = LDAPUtil.getUrl(userName);
    	LdapContextSource contextSource =
             new DefaultSpringSecurityContextSource(url);
    	
    	 contextSource.setUserDn(LDAPUtil.getUserDn(userName));
    	 contextSource.setPassword(LDAPUtil.getPassword(userName));
    	 contextSource.afterPropertiesSet();
    	 
        return contextSource;
    }
    
    /**
	 *  从LdapServer获得所有员工用户信息
	 *
	 */
 //   @SuppressWarnings("unchecked")
//	public List<User> getAllCompanyEmployeeInfoFromLdapServer(){
//    	List<User> result = new ArrayList<User>();
//    	
//    	final int PAGE_SIZE = 50;
//        SearchControls searchControls = new SearchControls();
//        searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
//        String base = "";
//        String filter = "(objectcategory=user)" ;
//
//        PagedResultsRequestControl requestControl;
//        requestControl = new PagedResultsRequestControl(PAGE_SIZE);
//        final Pattern p = Pattern.compile("((bl)|(tm))[0-9]{2,8}", Pattern.CASE_INSENSITIVE);
//        
//        AttributesMapper handler = new AttributesMapper() {
//            public Object mapFromAttributes(Attributes attrs) throws NamingException {
//            	Matcher m = p.matcher(getStringAttr(attrs, "samaccountname"));
//            	if(m.matches()){
//	            	User result = new User();
//	            	UserProfile userProfile = new UserProfile();
//	        		result.setUserProfile(userProfile);
//	        		
//	        			result.setUsername(getStringAttr(attrs, "samaccountname"));
//		        		result.setName(getStringAttr(attrs, "name"));
//		                userProfile.setCity(getStringAttr(attrs, "l"));
//		                userProfile.setDepartment(getStringAttr(attrs, "department"));
//		        		userProfile.setPostCode(getStringAttr(attrs, "postalcode"));
//		        		userProfile.setTelephoneExtention(getStringAttr(attrs, "telephoneNumber"));
//		        		userProfile.setEmail(getStringAttr(attrs, "mail"));
//		        		System.out.println(result.getUsername() + ":" + result);
//	            	return result;
//            	}else{
//            		return null;
//            	}
//            }
//            private String getStringAttr(Attributes attrs, String attrName){
//            	Attribute o = attrs.get(attrName);
//            	try {
//					if(o != null && o.get() != null){
//						return (String)o.get();
//					}
//				} catch (javax.naming.NamingException e) {
//					e.printStackTrace();
//				}
//				return "";
//            }
//         };
//        
//        result.addAll(ldapTemplate.search(base, filter, searchControls, handler, requestControl));
//        PagedResultsCookie cookie = requestControl.getCookie();
//        while(cookie != null && cookie.getCookie() != null){
//        	result.addAll(ldapTemplate.search(base, filter, searchControls, handler, requestControl));
//        	cookie = requestControl.getCookie();
//        }
//        return result;
//    	
//    	
//    }
    
	@SuppressWarnings({ "rawtypes" })
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
		
		List users = sqlSessionTemplate.selectList(getStatementPrefix() + GET_BY_USERNAME ,userName);
		
        if (users == null || users.isEmpty()) {
            throw new UsernameNotFoundException(ErrorCode.USER_NOT_EXIST);
        } else {
        	User user = (User)users.get(0);
        	user.setRoles(roleDao.getRolesByUserID(user.getId()));
        	user.getAuthorities();
        	return user;
        } 
    }
	@SuppressWarnings("unchecked")
	public List<User> getUsersByRoleGroupId(Long roleGroupId) {
		List<User> result = null;
    	try{
    		result = getSqlSessionTemplate().selectList(getStatementPrefix() + GET_BY_GROUP_ID ,roleGroupId);
        	return result;
    	}
    	catch(UsernameNotFoundException e){
    		return result;
    	}
	}

	@Override
    public void removeUserGroup(Long userid) {
        try {
            sqlSessionTemplate.delete(getStatementPrefix() + "deleteUserGroup", userid);
        } catch (Exception e) {
            logger.error(getStatementPrefix() + "error occured when method deleteUserGroup invocked.");
            logger.error(e);
            e.printStackTrace();
            throw new DAOException(e);
        }
    }

	/**
	 * 根据groupId删除CRM_USER_ROLEGROUP的记录
	 * @param groupId
	 */
	@Override
    public void removeUserGroupByGroupId(Long groupId) {
        try {
            sqlSessionTemplate.delete(getStatementPrefix() + "deleteUserGroupByGroupId", groupId);
        } catch (Exception e) {
            logger.error(getStatementPrefix() + "error occured when method remove invocked.");
            logger.error(e);
            e.printStackTrace();
            throw new DAOException(e);
        }
    }
	
    @Override
    public void createUserGroup(UserGroupMapping object) {
        try {
            sqlSessionTemplate.insert(getStatementPrefix() + "insertUserGroup", object);
        } catch (Exception e) {
            logger.error(getStatementPrefix() + "error occured when method insertUserGroup invocked.");
            logger.error(e);
            e.printStackTrace();
            throw new DAOException(e);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<UserGroupMapping> getUserGroupByUserID(Long userid) {
        List<UserGroupMapping> result = getSqlSession().selectList(getStatementPrefix()+"getUserGroupByUserID",userid);
        return result;
    }
    
    @Override
    public void removeUserRole(Long userid) {
        try {
            sqlSessionTemplate.delete(getStatementPrefix() + "deleteUserRole", userid);
        } catch (Exception e) {
            logger.error(getStatementPrefix() + "error occured when method deleteUserRole invocked.");
            logger.error(e);
            e.printStackTrace();
            throw new DAOException(e);
        }
    }
    /**
	 * 根据groupId删除CRM_USER_ROLE的记录
	 * @param groupId
	 */
    @Override
    public void removeUserRoleByRoleGroupId(Long groupId) {
        try {
            sqlSessionTemplate.delete(getStatementPrefix() + "deleteUserRoleByGroupId", groupId);
        } catch (Exception e) {
            logger.error(getStatementPrefix() + "error occured when method remove invocked.");
            logger.error(e);
            e.printStackTrace();
            throw new DAOException(e);
        }
    }
    @Override
    public void createUserRole(UserRoleMapping object) {
        try {
            sqlSessionTemplate.insert(getStatementPrefix() + "insertUserRole", object);
        } catch (Exception e) {
            logger.error(getStatementPrefix() + "error occured when method insertUserRole invocked.");
            logger.error(e);
            e.printStackTrace();
            throw new DAOException(e);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<UserRoleMapping> getUserRoleByUserID(Long userid) {
        List<UserRoleMapping> result = getSqlSession().selectList(getStatementPrefix()+"getUserRoleByUserID",userid);
        return result;
    }
    
	@SuppressWarnings("rawtypes")
	@Override
	public User getUserByUsername(String username) {
		List users = sqlSessionTemplate.selectList(getStatementPrefix() + GET_BY_USERNAME ,username);
		
        if (users == null || users.isEmpty()) {
        	return null;
        } else {
        	User user = (User)users.get(0);
        	user.setRoles(roleDao.getRolesByUserID(user.getId()));
            return user;
        } 
	}
}
